package index

import (
	"encoding/json"
	"gq_volunteer_platform/bean"
	"gq_volunteer_platform/model/activity"
	"gq_volunteer_platform/model/help_request"
	"gq_volunteer_platform/model/news"
	"gq_volunteer_platform/model/point_application"
	"gq_volunteer_platform/model/user"
	"time"

	ServiceAdmin "gq_volunteer_platform/service/admin"

	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
)

func Index(c *gin.Context) {

	var organization_my_ids, err = ServiceAdmin.MyOrganizationIds(c, 0)
	if err != nil {
		bean.Log.Warning(err)
		c.String(400, err.Error())
		return
	}

	// 志愿者总数
	var one struct {
		UserCount uint
	}

	// 我的志愿者总数
	if err := bean.MysqlDb.Model(&user.User{}).Select("count(*) as user_count").Where("`organization_id` in ?", organization_my_ids).Where("`check_status`=?", "已审核").First(&one).Error; err != nil {
		bean.Log.Warning(err)
		c.String(400, err.Error())
		return
	}

	// 我的 志愿者 有积分
	var one2 struct {
		UserCount uint
	}

	if err := bean.MysqlDb.Model(&user.User{}).Select("count(*) as user_count").Where("`organization_id` in ?", organization_my_ids).Where("`check_status`=?", "已审核").Where("`point`<>?", 0).First(&one2).Error; err != nil {
		bean.Log.Warning(err)
		c.String(400, err.Error())
		return
	}

	// 我的 志愿者 党员
	var one3 struct {
		UserCount uint
	}

	if err := bean.MysqlDb.Model(&user.User{}).Select("count(*) as user_count").Where("`organization_id` in ?", organization_my_ids).Where("`check_status`=?", "已审核").Where("`political_status`=?", "中共党员").First(&one3).Error; err != nil {
		bean.Log.Warning(err)
		c.String(400, err.Error())
		return
	}

	// 查询近半年数据

	// 当月活动次数
	var yearMonth []string // mysql in 查询

	type Activity struct {
		YearMonth string
		Label     string
		ModelType string
		Count     uint
	}

	var ThisActivityMap Activity

	var ThisTrainMap Activity

	var ActivityMap []Activity // 要返回的结构 解决 mysql group null 不返回问题

	var TrainMap []Activity

	var ActivityList []Activity // orm 绑定

	// var UserMap []Activity // 志愿者人数

	var ThisYearMonth = time.Now().Format("2006-01")

	// 我的
	// 获取最近半年数据
	// 填充空数据
	for i := 5; i >= 0; i-- {
		// 查询条件加入
		var LoopYearMonth = time.Now().AddDate(0, -i, 0).Format("2006-01")
		yearMonth = append(yearMonth, LoopYearMonth)

		var two Activity
		two.YearMonth = LoopYearMonth
		two.Label = two.YearMonth[5:] + "月"
		two.ModelType = "活动"

		ActivityMap = append(ActivityMap, two)

		var two2 Activity
		two2.YearMonth = LoopYearMonth
		two2.Label = two2.YearMonth[5:] + "月"
		two2.ModelType = "培训"

		TrainMap = append(TrainMap, two2)
	}

	if err := bean.MysqlDb.Model(&activity.Activity{}).
		Select("`year_month`", "`model_type`", "COUNT(*) as count").
		Where("`organization_id` in ?", organization_my_ids).
		Where("`year_month` in ?", yearMonth).
		Where("`status` in ('招募中','进行中','已结束')").
		Group("`year_month`").
		Group("`model_type`").
		Find(&ActivityList).Error; err != nil {

		bean.Log.Warning(err)
		c.String(500, err.Error())
		return
	}

	for _, item := range ActivityList {
		if item.ModelType == "活动" {
			//ThisYearMonth
			if item.YearMonth == ThisYearMonth {
				ThisActivityMap = item
			}
			//map
			for index2, item2 := range ActivityMap {
				if item.YearMonth == item2.YearMonth {
					ActivityMap[index2].Count = item.Count
				}
			}
		}
		if item.ModelType == "培训" {
			//ThisYearMonth
			if item.YearMonth == ThisYearMonth {
				ThisTrainMap = item
			}
			//map
			for index2, item2 := range TrainMap {
				if item.YearMonth == item2.YearMonth {
					TrainMap[index2].Count = item.Count
				}
			}
		}
	}

	// orm 查询出的数据并入到 map 中

	// Chinese Communist Party
	// CCP
	// 计算服务时长
	ActivityServeHourMap, err := getActivityServeHourMap(yearMonth, organization_my_ids)
	if err != nil {
		bean.Log.Warning(err)
		c.String(500, err.Error())
		return
	}

	// 活动人数统计
	ActivityUserMap, err := getActivityUserMap(yearMonth, organization_my_ids)
	if err != nil {
		bean.Log.Warning(err)
		c.String(500, err.Error())
		return
	}

	// 代办工作
	MyWork, err := getMyWork(organization_my_ids)
	if err != nil {
		bean.Log.Warning(err)
		c.String(500, err.Error())
		return
	}

	c.PureJSON(200, gin.H{
		"UserCount":         one.UserCount,
		"UserCountHasPoint": one2.UserCount,
		"UserCountCCP":      one3.UserCount,
		"ActivityMap":       ActivityMap,
		"TrainMap":          TrainMap,
		"ThisActivityMap":   ThisActivityMap,
		"ThisTrainMap":      ThisTrainMap,

		"ActivityServeHourMap": ActivityServeHourMap,
		"ActivityUserMap":      ActivityUserMap,

		"MyWork": MyWork,
	})
}

// 服务时长
func getActivityServeHourMap(yearMonth []string, organization_my_ids []uint) (any, error) {

	type Activity_ struct {
		Name  string
		Count uint
	}

	// 服务时长统计
	type ServeHour struct {
		YearMonth string
		Label     string
		Count     uint
		Activity  []Activity_
	}

	var ServeHourMap []ServeHour // 服务时长统计
	var ServeHourList []struct {
		YearMonth string
		Name      string
		Label     string
		Count     uint
	} // orm 绑定

	// 填充空数据
	for i := 5; i >= 0; i-- {
		// 查询条件加入
		var LoopYearMonth = time.Now().AddDate(0, -i, 0).Format("2006-01")
		yearMonth = append(yearMonth, LoopYearMonth)

		// 服务时长统计
		var three ServeHour
		three.YearMonth = LoopYearMonth
		three.Label = three.YearMonth[5:] + "月"
		three.Count = 0
		three.Activity = []Activity_{}

		ServeHourMap = append(ServeHourMap, three)
	}

	//////////////////////////////// 服务时长统计 ////////////////////////////////
	if err := bean.MysqlDb.Model(&activity.Activity{}).
		Select("`activity`.`name`", "`year_month`", "CONCAT(RIGHT(`year_month`, 2), '月') as label", "serve_hour as count").
		Where("`organization_id` in ?", organization_my_ids).
		Where("`year_month` in ?", yearMonth).
		Where("`status` in ('招募中','进行中','已结束')").
		Find(&ServeHourList).Error; err != nil {

		return "", err
	}

	for _, item := range ServeHourList {
		//map
		for index2, item2 := range ServeHourMap {
			if item.YearMonth == item2.YearMonth {
				// ServeHourMap[index2].Count = item.Count
				var tmp Activity_
				tmp.Name = item.Name
				tmp.Count = item.Count

				ServeHourMap[index2].Count += item.Count
				ServeHourMap[index2].Activity = append(ServeHourMap[index2].Activity, tmp)

			}
		}
	}

	return ServeHourMap, nil
}

// 活动人数统计
func getActivityUserMap2(yearMonth []string) (any, error) {
	_ = yearMonth
	jsonStr := `[{"YearMonth":"2025-02","Label":"02月","Count":7,"Activity":[{"Name":"学雷锋志愿02-1","Count":3},{"Name":"学雷锋志愿02-2","Count":4}]},{"YearMonth":"2025-03","Label":"03月","Count":30,"Activity":[{"Name":"学雷锋志愿03-1","Count":3},{"Name":"学雷锋志愿03-2","Count":4},{"Name":"学雷锋志愿03-3","Count":4},{"Name":"学雷锋志愿03-4","Count":4},{"Name":"学雷锋志愿03-5","Count":7}]},{"YearMonth":"2025-04","Label":"04月","Count":0,"Activity":[]},{"YearMonth":"2025-05","Label":"05月","Count":15,"Activity":[{"Name":"学雷锋志愿05-1","Count":3},{"Name":"学雷锋志愿05-2","Count":4},{"Name":"学雷锋志愿05-3","Count":7}]},{"YearMonth":"2025-06","Label":"06月","Count":10,"Activity":[{"Name":"学雷锋志愿06-1","Count":1},{"Name":"学雷锋志愿06-2","Count":2},{"Name":"学雷锋志愿06-3","Count":4}]},{"YearMonth":"2025-07","Label":"07月","Count":1,"Activity":[{"Name":"学雷锋志愿07-1","Count":1}]}]`
	var data any
	json.Unmarshal([]byte(jsonStr), &data)

	return data, nil
}

// 活动人数统计
func getActivityUserMap(yearMonth []string, organization_my_ids []uint) (any, error) {

	type Activity_ struct {
		Name  string
		Count uint
	}

	type ActivityUser struct {
		YearMonth string
		Label     string
		Count     uint
		Activity  []Activity_
	}

	var ActivityUserMap []ActivityUser // 服务时长统计
	var ActivityUserList []struct {
		YearMonth string
		Name      string
		Label     string
		Count     uint
	} // orm 绑定

	// 填充空数据
	for i := 5; i >= 0; i-- {
		// 查询条件加入
		var LoopYearMonth = time.Now().AddDate(0, -i, 0).Format("2006-01")
		yearMonth = append(yearMonth, LoopYearMonth)

		// 活动人数统计
		var three ActivityUser
		three.YearMonth = LoopYearMonth
		three.Label = three.YearMonth[5:] + "月"
		three.Count = 0
		three.Activity = []Activity_{}
		ActivityUserMap = append(ActivityUserMap, three)
	}

	//////////////////////////////// 活动人数统计 ////////////////////////////////
	// 包含未签到人数
	if err := bean.MysqlDb.Model(&activity.Activity{}).
		Select("`activity`.`name`", "`year_month`", "CONCAT(RIGHT(`year_month`, 2), '月') as label", "participant_count as count").
		Where("`organization_id` in ?", organization_my_ids).
		Where("`activity`.`year_month` in ?", yearMonth).
		Where("`status` in ('招募中','进行中','已结束')").
		Find(&ActivityUserList).Error; err != nil {

		return "", err
	}

	for _, item := range ActivityUserList {
		//map
		// fmt.Println("item=======================", item)
		for index2, item2 := range ActivityUserMap {

			if item.YearMonth == item2.YearMonth {
				var tmp Activity_
				tmp.Name = item.Name
				tmp.Count = item.Count

				ActivityUserMap[index2].Count += item.Count
				ActivityUserMap[index2].Activity = append(ActivityUserMap[index2].Activity, tmp)
			}
		}
	}

	return ActivityUserMap, nil
}

// 获取我的待办工作（待审核）
func getMyWork(organization_my_ids []uint) (any, error) {

	type MyWork struct {
		MyWaitCheckUser uint // 我的待审核用户数量
		MyWaitActivity  uint // 我的待审核活动数量
		MyWaitTrain     uint // 我的待审核培训数量
		MyWaitNews      uint // 我的待审核新闻数量

		MyWaitBudeng uint // 我的待审核时长补登
		MyWaitHelp   uint // 我的待审核求助
	}

	var one MyWork

	// var organization_my_ids, err = ServiceAdmin.MyOrganizationIds(c, 0)
	// if err != nil {
	// 	return "", nil
	// }

	// MyWaitCheckUser 我的待审核用户数量
	if err := bean.MysqlDb.Model(&user.User{}).
		Select("count(1) as count").
		Where("`organization_id` in ?", organization_my_ids).
		Where("`check_status` = '待审核'").
		Find(&one.MyWaitCheckUser).Error; err != nil {

		return "", err
	}

	// MyWaitActivity 我的待审核活动数量
	if err := bean.MysqlDb.Model(&activity.Activity{}).
		Select("count(1) as count").
		Where("`organization_id` in ?", organization_my_ids).
		Where("`status` = '待审核'").
		Where("`model_type` = '活动'").
		Find(&one.MyWaitActivity).Error; err != nil {

		return "", err
	}

	// MyWaitTrain 我的待审核活动数量
	if err := bean.MysqlDb.Model(&activity.Activity{}).
		Select("count(1) as count").
		Where("`organization_id` in ?", organization_my_ids).
		Where("`status` = '待审核'").
		Where("`model_type` = '培训'").
		Find(&one.MyWaitTrain).Error; err != nil {

		return "", err
	}

	// MyWaitNews 待审核新闻数量
	if err := bean.MysqlDb.Model(&news.News{}).
		Select("count(1) as count").
		Where("`check_status` = '待审'").
		Find(&one.MyWaitNews).Error; err != nil {

		return "", err
	}

	// MyWaitBudeng 待审核时长补登
	if err := bean.MysqlDb.Model(&point_application.PointApplication{}).
		Select("count(1) as count").
		Where("`check_status` = '待审核'").
		Find(&one.MyWaitBudeng).Error; err != nil {

		return "", err
	}

	// MyWaitHelp 未读求助数量
	if err := bean.MysqlDb.Model(&help_request.HelpRequest{}).
		Select("count(1) as count").
		Where("`organization_id` in ?", organization_my_ids).
		Where("`status` = '未读'").
		Find(&one.MyWaitHelp).Error; err != nil {

		return "", err
	}

	return one, nil
}

// 导出统计数据
func ExportXlsx(c *gin.Context) {

	var req struct {
		StartDate string `binding:"datetime=2006-01"`
		EndDate   string `binding:"datetime=2006-01"`
	}

	if err := c.ShouldBindQuery(&req); err != nil {
		bean.Log.Warning(err)
		c.String(400, err.Error())
		return
	}

	start, err := time.ParseInLocation("2006-01", req.StartDate, time.Local)
	if err != nil {
		bean.Log.Warning(err)
		c.String(400, err.Error())
		return
	}

	end, err := time.ParseInLocation("2006-01", req.EndDate, time.Local)
	if err != nil {
		bean.Log.Warning(err)
		c.String(400, err.Error())
		return
	}

	organization_my_ids, err := ServiceAdmin.MyOrganizationIds(c, 0)
	if err != nil {
		bean.Log.Warning(err)
		c.String(400, err.Error())
		return
	}

	dataList, err := getExportData(monthsInclusive(start, end), organization_my_ids)
	if err != nil {
		bean.Log.Warning(err)
		c.String(500, err.Error())
		return
	}

	// fmt.Println(dataList)
	// b, _ := excelize.CoordinatesToCellName(2, 1)
	// fmt.Println(b)
	// return

	// c.PureJSON(200, activityList)
	// return
	// 1. 打开模板文件
	f, err := excelize.OpenFile("temp.xlsx")
	if err != nil {
		bean.Log.Warning(err)
		c.String(500, err.Error())
		return
	}

	defer func() {
		if err := f.Close(); err != nil {
			bean.Log.Warning(err)
		}
	}()

	// 循环起始位置B3
	var first_x = 2
	var first_y_init, first_y = 2, 2
	// 每次循环，处理一列数据，col
	for _, act := range dataList {
		// fmt.Println("=========================")
		// act.
		cellName, err := excelize.CoordinatesToCellName(first_x, first_y)
		// fmt.Println(first_x, first_y, cellName)
		if err != nil {
			bean.Log.Warning(err)
			c.String(500, err.Error())
			return
		}

		f.SetCellValue("Sheet1", cellName, act.Type) // 活动类型

		first_y += 1
		cellName, err = excelize.CoordinatesToCellName(first_x, first_y)
		// fmt.Println(first_x, first_y, cellName)
		if err != nil {
			bean.Log.Warning(err)
			c.String(500, err.Error())
			return
		}

		f.SetCellValue("Sheet1", cellName, act.Name) // 活动名称 name1|name2|name3

		first_y += 1
		cellName, err = excelize.CoordinatesToCellName(first_x, first_y)
		if err != nil {
			bean.Log.Warning(err)
			c.String(500, err.Error())
			return
		}

		f.SetCellValue("Sheet1", cellName, act.UserCount) // 志愿者人数

		first_y += 1
		cellName, err = excelize.CoordinatesToCellName(first_x, first_y)
		if err != nil {
			bean.Log.Warning(err)
			c.String(500, err.Error())
			return
		}

		f.SetCellValue("Sheet1", cellName, act.ServeHour) // 志愿者服务时长

		first_y += 1
		cellName, err = excelize.CoordinatesToCellName(first_x, first_y)
		if err != nil {
			bean.Log.Warning(err)
			c.String(500, err.Error())
			return
		}

		f.SetCellValue("Sheet1", cellName, act.ServePeopleNum) // 志愿者群众人数
		first_x += 1
		first_y = first_y_init
	}

	// 2. 填充数据（这里可以从请求参数或数据库获取）
	// f.SetCellValue("Sheet1", "B2", c.Query("name"))
	// f.SetCellValue("Sheet1", "C2", c.Query("age"))
	// f.SetCellValue("Sheet1", "D5", c.Query("department"))

	// 3. 设置响应头
	var filename = req.StartDate + "~" + req.EndDate

	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", "attachment; filename="+filename+".xlsx")
	c.Header("Content-Transfer-Encoding", "binary")

	// 4. 写入响应
	if err := f.Write(c.Writer); err != nil {
		c.PureJSON(500, err.Error())
	}

}

// 导出数据结构
type ExportData struct {
	Name           string
	Type           string
	ServeHour      uint
	UserCount      uint
	ServePeopleNum uint
}

func getExportData(yearMonth []string, organization_my_ids []uint) ([]ExportData, error) {

	var ActivityList []ExportData // orm 绑定

	if err := bean.MysqlDb.Model(&activity.Activity{}).
		Select("GROUP_CONCAT(`name` SEPARATOR '|') as name", "`type`", "SUM(`serve_hour`) as serve_hour", "SUM(`participant_count`) as user_count", "SUM(`serve_people_num`) as serve_people_num").
		Where("`organization_id` in ?", organization_my_ids).
		Where("`year_month` in ?", yearMonth).
		Where("`status` in ('招募中','进行中','已结束')").
		Where("`model_type` = '活动'").
		Group("`type`").
		Find(&ActivityList).Error; err != nil {

		bean.Log.Warning(err)
		return nil, err
	}

	return ActivityList, nil
}

// 计算时间之内的月份数
func monthsInclusive(start, end time.Time) []string {

	if start.After(end) {
		start, end = end, start
	}

	var year_month []string
	current := start
	limit := 10 * 12 // 最大限制，十年数据
	for current.Before(end) || current.Equal(end) {
		if limit <= 0 {
			break
		}
		year_month = append(year_month, current.Format("2006-01"))
		current = current.AddDate(0, 1, 0) // 时间增加一个月
		limit--
	}

	return year_month
}
